/*************************************************** 
  This is an example for our Adafruit 16-channel PWM & Servo driver
  Servo test - this will drive 8 servos, one after the other on the
  first 8 pins of the PCA9685

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/815
  
  These drivers use I2C to communicate, 2 pins are required to  
  interface.

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing  
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

// Copyright © 2022, 撤硕发明家, All Rights Reserved 


#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);


#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

//以下7行为自行调整的参数（备注：sg90舵机 500us=0°, 2400us=180°,除以4就是 pulse length）
#define PressUpper  300 // This is the upper location of pressing (这是按弦部分高位）
#define PressRange  80 // This is Range of pressing (这是按弦部分移动范围）
int PluckLeft[6]={300,300,300,300,300,300}; // This is the left position of pluck (这是拨弦左侧，依次为1到6弦)
int PluckRight[6]={400,400,400,400,400,400}; // This is the right position of pluck (这是拨弦右侧，依次为1到6弦)
int Beat= 300;//This is the bpm(节奏）
char ChordChoose[] = {'C','G','A','E','F','C','F','G'};//This is the chord flow（这是和弦走向）
int Rhythm=4;//（这是节奏型，53231323选4；532131选3）
//以上7行为自行调整的参数

uint8_t TEM[8]={0,0,0,0,0,0,0,0};
char CurrentChord;
int ConditionOfPluck[6]={1,1,1,1,1,1};

void Pluck(char CurrentChord,int Rhythm, int Beat){
  if(Rhythm==4){
    uint8_t C[]={5,3,2,3,1,3,2,3};
    uint8_t G[]={6,3,2,3,1,3,2,3};
    uint8_t A[]={4,3,2,3,1,3,2,3};
    uint8_t F[]={4,3,2,3,1,3,2,3};
    uint8_t E[]={6,3,2,3,1,3,2,3};
    switch(CurrentChord){
      case 'C':
        for(int y=0;y<8;y++){TEM[y]=C[y];}break;
      case 'G':
        for(int y=0;y<8;y++){TEM[y]=G[y];}break;
      case 'A':
        for(int y=0;y<8;y++){TEM[y]=A[y];}break;
      case 'E':  
        for(int y=0;y<8;y++){TEM[y]=E[y];}break;
      case 'F':  
        for(int y=0;y<8;y++){TEM[y]=C[y];}break;}
        
        for(int x=0;x<8;x++){
          delay(30000/Beat);
          if(ConditionOfPluck[TEM[x]-1]==1){
            pwm.setPWM(TEM[x]+9,0,PluckLeft[TEM[x]-1]);
            ConditionOfPluck[TEM[x]-1]=1-ConditionOfPluck[TEM[x]-1];
            Serial.print(TEM[x]);Serial.println("left");}
          else{
            pwm.setPWM(TEM[x]+9,0,PluckRight[TEM[x]-1]);
            ConditionOfPluck[TEM[x]-1]=1-ConditionOfPluck[TEM[x]-1];
            Serial.print(TEM[x]);Serial.println("Right");}
          delay(30000/Beat);
          for(int n=0;n<6;n++){Serial.print(ConditionOfPluck[n]);Serial.print(",");}
          Serial.println();  
        } 
  } 
  if(Rhythm==3){
    uint8_t C[]={5,3,2,3,1,3};
    uint8_t G[]={6,3,2,3,1,3};
    uint8_t A[]={4,3,2,3,1,3};
    uint8_t F[]={4,3,2,3,1,3};
    uint8_t E[]={6,3,2,3,1,3};
    switch(CurrentChord){
      case 'C':
        for(int y=0;y<6;y++){TEM[y]=C[y];}
        break;
      case 'G':
        for(int y=0;y<6;y++){TEM[y]=G[y];}
        break;
      case 'A':
        for(int y=0;y<6;y++){TEM[y]=A[y];}
        break;
      case 'E':  
        for(int y=0;y<6;y++){TEM[y]=E[y];}
        break;
      case 'F':  
        for(int y=0;y<6;y++){TEM[y]=C[y];}
        break;}
        
        for(int x=0;x<6;x++){
          delay(30000/Beat);
          if(ConditionOfPluck[TEM[x]-1]==1){
            pwm.setPWM(TEM[x]+9,0,PluckLeft[TEM[x]-1]);
            ConditionOfPluck[TEM[x]-1]=1-ConditionOfPluck[TEM[x]-1];}
          else{
            pwm.setPWM(TEM[x]+9,0,PluckRight[TEM[x]-1]);
            ConditionOfPluck[TEM[x]-1]=1-ConditionOfPluck[TEM[x]-1];}
          delay(30000/Beat);   
        }
  }
}

void Press(char CurrentChord){
  switch(CurrentChord){
    case 'C':
      pwm.setPWM(0,0,PressUpper-PressRange);pwm.setPWM(2,0,PressUpper-PressRange);pwm.setPWM(6,0,PressUpper+PressRange);Serial.print("current chord is:");Serial.println(CurrentChord);
      break;
    case 'G':
      pwm.setPWM(1,0,PressUpper-PressRange);pwm.setPWM(4,0,PressUpper-PressRange);pwm.setPWM(5,0,PressUpper+PressRange);Serial.print("current chord is:");Serial.println(CurrentChord);
      break;
    case 'A':
      pwm.setPWM(0,0,PressUpper-PressRange);pwm.setPWM(2,0,PressUpper-PressRange);pwm.setPWM(3,0,PressUpper+PressRange);Serial.print("current chord is:");Serial.println(CurrentChord);
      break;
    case 'E':
      pwm.setPWM(1,0,PressUpper-PressRange);pwm.setPWM(2,0,PressUpper-PressRange);Serial.print("current chord is:");Serial.println(CurrentChord);
      break;
    case 'F':
      pwm.setPWM(0,0,PressUpper-PressRange);pwm.setPWM(3,0,PressUpper+PressRange);pwm.setPWM(7,0,PressUpper-PressRange);Serial.print("current chord is:");Serial.println(CurrentChord);               
      break;
  }
}
void UnPress(char CurrentChord){
  switch(CurrentChord){
    case 'C':
      pwm.setPWM(0,0,PressUpper);pwm.setPWM(2,0,PressUpper);pwm.setPWM(6,0,PressUpper);Serial.println(CurrentChord);Serial.println("is back");
      break;
    case 'G':
      pwm.setPWM(1,0,PressUpper);pwm.setPWM(4,0,PressUpper);pwm.setPWM(5,0,PressUpper);Serial.println(CurrentChord);Serial.println("is back");
      break;
    case 'A':
      pwm.setPWM(0,0,PressUpper);pwm.setPWM(2,0,PressUpper);pwm.setPWM(3,0,PressUpper);Serial.println(CurrentChord);Serial.println("is back");
      break;
    case 'E':
      pwm.setPWM(1,0,PressUpper);pwm.setPWM(2,0,PressUpper);Serial.println(CurrentChord);Serial.println("is back");
      break;
    case 'F':
      pwm.setPWM(0,0,PressUpper);pwm.setPWM(3,0,PressUpper);pwm.setPWM(7,0,PressUpper);Serial.println(CurrentChord);Serial.println("is back");       
      break;
  }
}

void setup() {
  Serial.begin(9600);
  Serial.println("RESET");
  pwm.begin(); 
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates
  for(int n = 11;n < 16;n++){
    pwm.setPWM(n,0,PluckLeft);
  }
  for(int n = 0;n < 8;n++){
    pwm.setPWM(n,0,PressUpper);
  }
  delay(2000);
}

void loop() {
  int ChordSize=sizeof(ChordChoose)/sizeof(ChordChoose[0]);
  for(int n=0;n<ChordSize;n++){
    CurrentChord=ChordChoose[n];
    Press(CurrentChord);
    Pluck(CurrentChord,Rhythm,Beat);
    UnPress(CurrentChord);
  }
}
    
